package com.jacky.util;

import android.content.Context;
import android.graphics.Rect;
import android.hardware.Camera;
import android.os.Build;
import android.os.Handler;
import android.util.Size;
import android.view.Surface;
import android.view.WindowManager;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.logging.Logger;

public class OcrRectManager {

    /// android 64位不支持
    public static boolean supportOcr(Context context) {
         String s = context.getApplicationInfo().nativeLibraryDir;
        OcrLogger.i(s);
        return(!s.endsWith("arm64"));
    }

    ///获取手机相机方向 https://zhuanlan.zhihu.com/p/110944780
    public static int getCameraOrientation(int cameraId){
        Camera.CameraInfo info =new Camera.CameraInfo();
        Camera.getCameraInfo(cameraId,info);
        return info.orientation;
    }

    ///显示方向
    public static int getDisplayOrientation(Context context){
        WindowManager windowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
        int or = windowManager.getDefaultDisplay().getRotation();
        switch (or){
            case Surface.ROTATION_90 : return 90;
            case Surface.ROTATION_180 : return 180;
            case Surface.ROTATION_270 : return 270;
            case Surface.ROTATION_0 :
            default:
                return 0;
        }
    }

    public static int getCameraAngle(Context context,int cameraId){
        //来自 Camera.setDisplayOrientation
        int degrees = getDisplayOrientation(context);
        int orientation = getCameraOrientation(cameraId);
        int result;
        if (cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {  // back-facing
            result = (orientation - degrees + 360) % 360;
        }
//        OcrLogger.d("tag","flutter to android, getDisplayOrientation " + degrees + " orientation "
//                + orientation+ " result " + result);
        return result;
    }

    public static OcrRectManager get(Context context, Handler handler) {
        if(supportOcr(context))
            return new OcrRectManager32(context, handler);
        return new OcrRectManager();
    }

//    private static boolean isArm64() {
//        InputStream input = null;
//        try {
//            Process suProcess = Runtime.getRuntime().exec("getprop ro.product.cpu.abi");
//            input = suProcess.getInputStream();
//
//            BufferedReader successResult = new BufferedReader(new InputStreamReader(input));
//            BufferedReader errorResult = new BufferedReader(
//                    new InputStreamReader(suProcess.getErrorStream()));
//            String s;
//            boolean isFinish = false;
//            while ((s = successResult.readLine()) != null) {
//                OcrLogger.e(s);
//                if ("arm64-v8a".equals(s)) {
//                    return true;
//                } else {
//                    return false;
//                }
//            }
////            while (!isFinish && (s = errorResult.readLine()) != null) {
////                OcrLogger.e(s);
////                isOk = false;
////            }
//        } catch (Exception e) {
//            OcrLogger.e(e);
//        } finally {
//            if(input != null) {
//                try {
//                    input.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
//        }
//        return true;
//    }

    public boolean isNeedUpdatePreviewSize(){
        return false;
    }

    public void setOcrRect(int previewWidth, int previewHeight, Rect rect){
    }

    /**
     * ocr识别摄像头
     */
    public void ocrRectData(byte[] data){
    }

    public void ocrRectData(byte[] data,int width,int height){
    }

    /**
     * 获取识别数据
     * @param imgFile 整个识别的图片保存路径
     * @param headFile 识别出来的头像图片保存路径
     * @return 识别内容
     */
    public String getRectResult(String imgFile,String headFile){
        return null;
    }



    private final Camera.PreviewCallback previewCallback = new Camera.PreviewCallback() {
        public void onPreviewFrame(byte[] data, Camera camera) {
            sendPreviewDataToOcr(data);
        }
    };

    /**
     * 将一帧数据发送给 主线程处理
     * @param data 一帧预览画面数据
     */
    public void sendPreviewDataToOcr(byte[] data){
    }

    /**
     * 获取摄像头单帧数据
     */
    public Camera.PreviewCallback getPreviewCallback(){
        return previewCallback;
    }

    /**
     * 根据ocr识别的信息，进行解析字段并返回
     * @param result ocr识别信息
     * @param imgPath 图片保存路径
     * @param headPath 头像图片保存路径
     */
    /**
     * 根据ocr识别的信息，进行解析字段并返回
     * @param result ocr识别信息
     * @param imgPath 图片保存路径
     * @param headPath 头像图片保存路径
     */
    public static HashMap<String, Object> handleResultCallback(String result, String imgPath, String headPath) {
        try {
            JSONObject json = new JSONObject(result);
            HashMap<String, Object> map = new HashMap<>();
            for (Iterator<String> iterator = json.keys(); iterator.hasNext(); ) {
                String key = iterator.next();
                String value = getValue(json, key);
                map.put(key.toLowerCase(), value);
            }
            map.put("imgPath", imgPath);
            map.put("headPath", headPath);
            return map;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static String getValue(JSONObject json, String key) throws JSONException {
        if (json != null && json.has(key)) {
            JSONObject value = json.optJSONObject(key);
            return value != null ? (String) value.opt("value") : null;
        }
        return null;
    }

    ///将屏幕画面的rect区域，转为摄像头画面rect 居中
    public static Rect getViewfinder(Rect rec,
                                     int viewWidth, int viewHeight,
                                     Size previewSize){
        return getViewfinder(rec, viewWidth,  viewHeight, previewSize,0,0);
    }

    ///将屏幕画面的rect区域，转为摄像头画面rect
    public static Rect getViewfinder(Rect rec,
                                     int viewWidth, int viewHeight,
                                     Size previewSize,int offsetCenterX,int offsetCenterY) {
        if (rec == null) {
            rec = new Rect(0, 0, viewWidth, viewHeight);
        }
        OcrLogger.d();
        if(viewWidth == 0 || viewHeight == 0 || previewSize.getHeight() == 0)return rec;
        //中点-宽高方法
        //rec是相对于view宽高的区域，rect是相对于preview宽高区域；rec到rect的比例，是view相对于preview比例，再根据angle进行旋转
        int viewW = Math.max(viewHeight,viewWidth);
        int viewH = Math.min(viewHeight,viewWidth);
        int previewW = Math.max(previewSize.getWidth(),previewSize.getHeight());
        int previewH = Math.min(previewSize.getWidth(),previewSize.getHeight());
        int recW = Math.max(rec.width(),rec.height());
        int recH = Math.min(rec.width(),rec.height());
//        float rectW = recW * previewW / (float)viewW;
//        float rectH = recH * previewH / (float)viewH;
        //将viewH、W变成比例为preview的宽高，再进行放大到viewH、viewW
        float previewR = previewW/(float)previewH;
        float viewR = viewW/(float)viewH;
        float tempH = viewW > previewR * viewH ? viewH : viewW / previewR;
        float tempW = viewH == tempH ? previewR * viewH : viewW;
        float scale = viewR > previewR ? viewR / previewR : previewR / viewR;
        float viewRateW = tempW * scale;
        float viewRateH = tempH * scale;
        float rectW = recW * previewW / viewRateW;
        float rectH = recH * previewH / viewRateH;
        int offsetX = viewWidth == viewW ? offsetCenterX : offsetCenterY;
        int offsetY = viewWidth == viewW ? offsetCenterY : -offsetCenterX;
        float centerW = previewW / 2f + offsetX;
        float centerH = previewH / 2f + offsetY;
        Rect rect = new Rect((int)(centerW - rectW/2),(int)(centerH - rectH/2),(int)(centerW + rectW/2),(int)(centerH + rectH/2));
//        OcrLogger.d("rect", rect, "previewSize", previewSize, "centerW", centerW, centerH, "rectW", rectW, rectH,
//                "recW", recW, recH, "viewW", viewW, viewH
//                , "tempW", tempW, tempH, "scale", scale, "viewRateW", viewRateW, viewRateH
//        );
        if(rect.left < 0) rect.left = 0;
        if(rect.top < 0) rect.top = 0;
        if(rect.right <= 0 || rect.right > previewW) rect.right = previewW;
        if(rect.bottom <= 0 || rect.bottom > previewH) rect.bottom = previewH;
        return rect;
    }
}
